// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;

using Microsoft.TeamFoundation.Migration.Toolkit;
using Microsoft.TeamFoundation.Migration.Toolkit.Wit;
using Microsoft.TeamFoundation.Migration.WorkItemTracking.Wss.Generated;

namespace Microsoft.TeamFoundation.Migration.WorkItemTracking.Wss
{
    /// <summary>
    /// Wss work item (task).
    /// </summary>
    internal sealed class WssMigrationWorkItem : IMigrationWorkItem
    {
        private WssTask m_task;                             //Data from the Wss task
        private string m_uri;                               //URI
        private Watermark m_watermark;                      //Watermark
        private MigrationWorkItemData m_flags;              //Flags
        private string m_tempDir;                           //Temp directory (for attachments)
                
        #region IMigrationWorkItem Members

        /// <summary>
        /// Returns work item's URI.
        /// </summary>
        public string Uri { get { return m_uri; } }

        /// <summary>
        /// Returns id of the work item.
        /// </summary>
        public Watermark Watermark
        {
            get { return m_watermark; }
        }

        /// <summary>
        /// Gets name of the work item type.
        /// </summary>
        public string WorkItemType
        {
            get { return "WssTask"; }
        }

        /// <summary>
        /// Tells the engine what kind of data the work item has.
        /// </summary>
        public MigrationWorkItemData Flags
        {
            get { return m_flags; }
        }

        /// <summary>
        /// Get the list of revisions.  Since this is flat, the revision part is irrelevant.  
        /// We'll just return the latest information.
        /// </summary>
        /// <param name="revision">Revision number.</param>
        /// <returns>Revision data</returns>
        public ReadOnlyCollection<MigrationRevision> GetRevisions(int revision)
        {
            List<MigrationRevision> l = new List<MigrationRevision>();
            MigrationRevision rev = new MigrationRevision(1, m_task.Editor, m_task.Modified);
            l.Add(rev);

            foreach (KeyValuePair<string, object> pair in m_task.Fields)
            {
                if (!WssFields.IsReadOnly(pair.Key))
                {
                    rev.Fields.Add(new MigrationField(pair.Key, pair.Value));
                }
            }

            return l.AsReadOnly();
        }

        /// <summary>
        /// Returns the most recent values of the given fields.
        /// </summary>
        /// <param name="fieldNames">Names of fields</param>
        /// <returns>Values</returns>
        public IEnumerable<MigrationField> GetLatestValues(
            IEnumerable<string> fieldNames)
        {
            // The method is used only for synchronization of flat work items, which are not
            // supported by the WSS adapter.
            throw new NotSupportedException();
        }

        /// <summary>
        /// Gets a list of files attached to a work item.
        /// </summary>
        /// <returns>List of attachments.</returns>
        public ReadOnlyCollection<IMigrationFileAttachment> GetFileAttachments()
        {
            AttachmentsAttachment[] files = m_task.GetAttachments();
            List<IMigrationFileAttachment> attachments = new List<IMigrationFileAttachment>(files.Length);

            for (int i = 0; i < files.Length; i++)
            {
                WssMigrationFileAttachment file = new WssMigrationFileAttachment(m_task, files[i].Value, m_tempDir);
                attachments.Add(file);
            }
            return attachments.AsReadOnly();
        }

        /// <summary>
        /// Customizes change list on the target side before it gets translated.
        /// </summary>
        /// <param name="target">Change list from the opposite side</param>
        public void OnTargetUpdate(IWorkItemUpdatePackage target)
        {
            //We don't need to do anything for this implementation.
        }

        #endregion


        #region Constructors
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="r">Row deserialized from Wss xml</param>
        public WssMigrationWorkItem(WssTask t, string tempDir)
        {
            m_task = t;
            m_tempDir = tempDir;
            m_uri = string.Format(CultureInfo.InvariantCulture, "wss:workitem:{0}", t.StringId);
            m_watermark = new Watermark(t.StringId, 1);
            m_flags = MigrationWorkItemData.None;
            if (t.HasAttachments)
            {
                m_flags = MigrationWorkItemData.Attachments;
            }
        }
        #endregion       
    }
}
